<?php

//需要在后期循环判断url上面加上缓存，提高解析URL的速度

class Router {

	private $ruleArr = null;
	private $rewrite = null;
	private static $instance = null;
	
	public static function getInstance() {
		if(is_null(self::$instance)){
			self::$instance = new router();
		}
		return self::$instance;
	}

	public function go($rewrite = false,$ruleArr=array()) {
		$this->ruleArr = $ruleArr;
		$this->rewrite = $rewrite; 
		import('libs/router/router.before.php');
		$execObj = $this->getRequestObject();
		import('libs/router/router.after.php');
		try{
			if(!empty($execObj)){
				importApp($execObj['filePath']);
				$this->call_func($execObj['urlArr']['m']);
			}
			else{
				throw new RouterException(404,'未找到该页');
			}
		} catch (RouterException $e) {
			$httpCode = $e->getHttpCode();
			log::error('httpCode:'.$httpCode.',message:'.$e->getMessage());
			t($this->ruleArr['httpError']["$httpCode"],array('errMsg'=>$e->getMessage()));
		}
	}

	public function buildURI($url) {
		if($this->rewrite){
			return $url;
		}
		$ruleArr = $this->ruleArr;
		while (list($key, $val) = each($ruleArr)){
			if($key==='httpError'){
				continue;
			}
			while(list($key1,$val1)=each($val)){
				$urlRewriteStr = "/^".str_replace("/","\/",$key1)."\/?$/i";
				if(preg_match($urlRewriteStr,$url,$matches)){
					parse_str($val1,$urlArr);
					$paramArr = array();
					$i = 1;
					while(list($key2,$val2) = each($urlArr)){
						if($key2==='f' || $key2==='m'){
							$paramArr["$key2"] = $val2;
						}
						else{
							$paramArr["$key2"] = $matches[$i];
							$i++;
						}
					}
					return basename($_SERVER['SCRIPT_FILENAME']).'?'.http_build_query($paramArr);
				}
			}
		}
	}

	private function getRequestObject() {
		$url = getRequestURL();
		$ruleArr = $this->ruleArr;
		while (list($key, $val) = each($ruleArr)){
			if($key==='httpError'){
				continue;
			}
			while(list($key1,$val1)=each($val)){
				if($this->rewrite){
					$urlRewriteStr = "/^".str_replace("/","\/",$key1)."\/?$/i";
					if(preg_match($urlRewriteStr,$url,$matches)){
						parse_str($val1,$urlArr);
						$i = 1;
						if(count($urlArr)-2 != count($matches)-1){
							 throw new RouterException(500,'url已经匹配成功，但是url所对应的链接错误');
						}
						while(list($key2,$val2) = each($urlArr)){
							if($key2!=='f' && $key2!=='m'){
								$_GET["$key2"] = $matches[$i];
								$i++;
							}
						}
						return array('filePath'=>$key,'urlArr'=>$urlArr);
					}
				}
				else{
					parse_str($val1,$urlArr);
					if($urlArr['f'] === $_GET['f'] && $urlArr['m'] === $_GET['m']){
						return array('filePath'=>$key,'urlArr'=>$urlArr);
					}
				}
			}
		}
	}

	private function call_func($func_name,$func_par=array()) {
		$func_name = $this->safe_deal($func_name);
		if(function_exists($func_name)){
			call_user_func_array($func_name,$func_par);
		}
		else{
			throw new RouterException(404,"未找到方法：".$func_name);
		}
	}

	private function safe_deal($str) {
		return str_replace(array('/', '.'), '', $str);
	}
}

class RouterException extends Exception {
	
	private $httpCode;

	function __construct($httpCode = 404,$errorMsg){
		parent::__construct($errorMsg);
		$this->httpCode = $httpCode;
	}

	public function getHttpCode() {
		return $this->httpCode;
	}
}